using System;
using System.IO;
using System.Linq;
using System.Data;
using System.Drawing;
using System.Reflection;
using System.Diagnostics;
using System.Collections;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;
using DevComponents.DotNetBar;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geoprocessing;
using PlanningGIS.Framework;
using PlanningGIS.Engine.Controls;
using PlanningGIS.Win.Controls;
using PlanningGIS.Util;
using PlanningGIS.ArcGIS;
using System.ComponentModel;
using PlanningGIS.Util.IO;
using PlanningGIS.Util.Log;

namespace PlanningGIS.Analysis
{
    /// <summary>
    /// 叠置分析窗体
    /// </summary>
    public partial class FrmOverlap : Office2007Form
	{
        /// <summary>
        /// 窗体实例
        /// </summary>
        private static FrmOverlap frmOverlap = null;
        /// <summary>
        /// 创建窗体实例
        /// </summary>
        /// <returns></returns>
        public static FrmOverlap CreateNewForm()
        {
            if (frmOverlap == null || frmOverlap.IsDisposed)
            {
                frmOverlap = new FrmOverlap();
                frmOverlap.InitializeComponent();
            }
            return frmOverlap;
        }

        /// <summary>
        /// 在这里加载所有的图层数据
        /// </summary>
        /// <param name="eventSender"></param>
        /// <param name="eventArgs"></param>
        private void FrmOverlap_Load(System.Object eventSender, System.EventArgs eventArgs)
        {
            //空间分析类型
            this.cmbOverlayType.DataSource = null;
            this.cmbOverlayType.ValueMember = "Value";
            this.cmbOverlayType.DisplayMember = "Name";
            List<ValueName> overlaptypes = new List<ValueName>()
            {
                new ValueName(){ Name=zjgisOverlapType.zjgisOverlapDiff.GetDescription(),Value=zjgisOverlapType.zjgisOverlapDiff.ToString()},
                new ValueName(){ Name=zjgisOverlapType.zjgisOverlapErase.GetDescription(),Value=zjgisOverlapType.zjgisOverlapErase.ToString()},
                new ValueName(){ Name=zjgisOverlapType.zjgisOverlapIntersect.GetDescription(),Value=zjgisOverlapType.zjgisOverlapIntersect.ToString()},
                new ValueName(){ Name=zjgisOverlapType.zjgisOverlapUnion.GetDescription(),Value=zjgisOverlapType.zjgisOverlapUnion.ToString()}
            };
            this.cmbOverlayType.DataSource = overlaptypes;

            //this.cmbOverlayType.Items.Clear();
            //this.cmbOverlayType.Items.Add("求差分析");
            //this.cmbOverlayType.Items.Add("擦除分析");
            //this.cmbOverlayType.Items.Add("求交分析");
            //this.cmbOverlayType.Items.Add("求并分析");
            //this.cmbOverlayType.Items.Add("定位分析");
            //this.cmbOverlayType.Items.Add("更新分析");
            this.cmbOverlayType.SelectedIndex = 0; //初始化为求差分析                          
            this.Image1.Image = this.imgTypes.Images[0];//初始化空间分析类型 

            //初始化属性来源，默认来源为所有
            this.cmbAtt.Items.Clear();
            this.cmbAtt.Items.Add("所有属性");
            this.cmbAtt.Items.Add("仅ID值");
            this.cmbAtt.Items.Add("排除ID");
            this.cmbAtt.Items.Add("仅原始属性");
            this.cmbAtt.SelectedIndex = 0;

            //添加分析范围
            this.cmbExtent.Items.Clear();
            this.cmbExtent.Items.Add("当前视图范围");
            this.cmbExtent.Items.Add("全局视图范围");
            this.cmbExtent.SelectedIndex = 1;

            try
            {
                //加载空间叠置分析类型
                cmblyrOrg.FeatureType = zjgisFeatureType.Vector;
                cmblyrOrg.ShapeType = zjgisShapeType.Polygon;
                cmblyrOrg.OnCreate(Hook);

                cmblyrOverlap.FeatureType = zjgisFeatureType.Vector;
                cmblyrOverlap.ShapeType = zjgisShapeType.Polygon;
                cmblyrOverlap.OnCreate(Hook);
            }
            catch(Exception ex )
            {
                MsgHelper.ShowErrorMsgbox(ex.Message);
            }
        }
        /// <summary>
        /// 叠置分析类型
        /// </summary>
        [Description("叠置分析类型")]
        private enum zjgisOverlapType
        {
            /// <summary>
            /// 求差分析
            /// </summary>
            [Description("求差分析")]
            zjgisOverlapDiff=0,
            /// <summary>
            /// 擦除分析
            /// </summary>
            [Description("擦除分析")]
            zjgisOverlapErase,
            /// <summary>
            /// 求交分析
            /// </summary>
            [Description("求交分析")]
            zjgisOverlapIntersect,
            /// <summary>
            /// 求并分析
            /// </summary>
            [Description("求并分析")]
            zjgisOverlapUnion            
        }
        ///// <summary>
        ///// 日志操作委托事件
        ///// </summary>
        //public WriteLog2 WriteLogEvent { get; set; }

        /// <summary>
        /// MapControl.Object
        /// </summary>
        public object Hook { get; set; }

        /// <summary>
        /// 当前的地图对象
        /// </summary>
        public IMap FocusMap;

        /// <summary>
        /// 选择叠置分析的类型
        /// </summary>
        /// <param name="eventSender"></param>
        /// <param name="eventArgs"></param>
        private void cmbOverlayType_SelectedIndexChanged(System.Object eventSender, System.EventArgs eventArgs)
        {
            this.Image1.Image = this.imgTypes.Images[cmbOverlayType.SelectedIndex];
        }

        /// <summary>
        /// 选择原始图层
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmblyrOrg_SelectedIndexChanged(object sender, EventArgs e)
        {
            ILayer lyr = cmblyrOrg.SelectedLayer;
            if (lyr == null)
                return;
            cmblyrOverlap.HideLayer(lyr);
            cmblyrOverlap.SelectedNode = null;
            Application.DoEvents();
            IFeatureLayer featureLayer = lyr as IFeatureLayer;
            IFeatureSelection tableSelection = featureLayer as IFeatureSelection;
            ISelectionSet selectionSet = tableSelection.SelectionSet;
            ChkLayer.Enabled = (selectionSet.Count > 0);
            Marshal.ReleaseComObject(selectionSet);
            selectionSet = null;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmblyrOverlap_SelectedIndexChanged(object sender, EventArgs e)
        {
            ILayer lyr = cmblyrOverlap.SelectedLayer;
            if (lyr == null)
                return; 
            IFeatureLayer featureLayer = lyr as IFeatureLayer;
            IFeatureSelection tableSelection = featureLayer as IFeatureSelection;
            ISelectionSet selectionSet = tableSelection.SelectionSet;
            chkOverLayer.Enabled = (selectionSet.Count > 0);            
            Marshal.ReleaseComObject(selectionSet);
            selectionSet = null;
        }
        
        /// <summary>
        /// 设置输出文件
        /// </summary>
        /// <param name="eventSender"></param>
        /// <param name="eventArgs"></param>
        private void CmdOutput_ClickEvent(System.Object eventSender, System.EventArgs eventArgs)
        {
            try
            {
                SaveDataDialog dlg = new SaveDataDialog();
                dlg.AllowReName = false;
                DialogResult rst = dlg.ShowDialog(this);
                if (rst != System.Windows.Forms.DialogResult.OK)
                    return;
                txtFile.Text = dlg.FullName;
            }
            catch (Exception ex)
            {
                MsgHelper.ShowErrorMsgbox("选择保存路径失败！" + ex.Message);
            }
        }

        /// <summary>
		/// 关闭
		/// </summary>
		/// <param name="eventSender"></param>
		/// <param name="eventArgs"></param>
		private void cmdCancel_ClickEvent(System.Object eventSender, System.EventArgs eventArgs)
		{
			this.Close();
		}

		/// <summary>
        /// 在这个里面，为了方便起见，对于IGeoprocessor提供的借口
        /// 这里根据实际的情况，来进行空间分析		
		/// </summary>
		/// <param name="eventSender"></param>
		/// <param name="eventArgs"></param>
        private void cmdOK_ClickEvent(System.Object eventSender, System.EventArgs eventArgs)
        {
            ILayer lyr1 = cmblyrOrg.SelectedLayer;
            ILayer lyr2 = cmblyrOverlap.SelectedLayer;
            if (lyr1 == null)
            {
                MsgHelper.ShowWarningMsgbox("请选择原始图层！");
                return;
            }
            if (lyr2 == null)
            {
                MsgHelper.ShowWarningMsgbox("请选择叠置图层！");
                return;
            }
            //输出文件是否填写
            if (this.txtFile.Text == "")
            {
                MsgHelper.ShowWarningMsgbox("请指定输出文件！");
                return;
            }
            DoOverlap(lyr1, lyr2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="lyr1"></param>
        /// <param name="lyr2"></param>
        private void DoOverlap(ILayer lyr1, ILayer lyr2)
        {
            zjgisOverlapType ovtype = (zjgisOverlapType)Enum.Parse(typeof(zjgisOverlapType), cmbOverlayType.SelectedValue.ToString());
            Progress.Value = 0;
            IFeatureLayer featLyrOrg = lyr1 as IFeatureLayer;
            IFeatureLayer featLyrOverlay = lyr2 as IFeatureLayer;
            string in_featureclass1 = GetLayerName(ChkLayer.Checked, featLyrOrg);
            string in_featureclass2 = GetLayerName(chkOverLayer.Checked, featLyrOverlay);
            if (string.IsNullOrWhiteSpace(in_featureclass1) || string.IsNullOrWhiteSpace(in_featureclass2))
            {
                MsgHelper.ShowErrorMsgbox("无法将输入图层转成所需的lyr数据，无法叠置分析");
                return;
            }
            if (in_featureclass1.Equals(in_featureclass2))
            {
                MsgHelper.ShowInfomationMsgbox("输入图层名称不能相同，请修改名称！");
                return;
            }
            this.CmdOK.Enabled = false;
            string[] JoinAttributes = { "ALL", "NO_FID", "ONLY_FID" };
            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor; //改变鼠标样式
            try
            {
                Geoprocessor GP = new Geoprocessor();
                string OutputName = GetOutName();
                IFeatureClass OutputFC = null;
                bool suc = false;
                string msg = "";
                if (ovtype == zjgisOverlapType.zjgisOverlapUnion || ovtype == zjgisOverlapType.zjgisOverlapDiff)
                {
                    ESRI.ArcGIS.AnalysisTools.Union union = new ESRI.ArcGIS.AnalysisTools.Union();
                    union.in_features = in_featureclass1 + ";" + in_featureclass2;
                    union.out_feature_class = OutputName;
                    if (ovtype == zjgisOverlapType.zjgisOverlapDiff)
                        union.join_attributes = "ALL";
                    else
                        union.join_attributes = JoinAttributes[this.cmbAtt.SelectedIndex];
                    union.gaps = "GAPS";
                    suc = GeoprocessorHelper.Execute(union, GP, out msg);
                    if (suc && ovtype == zjgisOverlapType.zjgisOverlapDiff)
                    {
                        IFeatureClass pFC = GP.Open(OutputName) as IFeatureClass;
                        string name1 = (featLyrOrg.FeatureClass as IDataset).Name;
                        string name2 = (featLyrOverlay.FeatureClass as IDataset).Name;
                        GetDiffFeatureClass(pFC, name1, name2);
                    }
                }
                else if (ovtype == zjgisOverlapType.zjgisOverlapErase)
                {
                    ESRI.ArcGIS.AnalysisTools.Erase erase = new ESRI.ArcGIS.AnalysisTools.Erase();
                    erase.in_features = in_featureclass1;
                    erase.erase_features = in_featureclass2;
                    erase.out_feature_class = OutputName;
                    suc = GeoprocessorHelper.Execute(erase, GP, out msg);
                }
                else if (ovtype == zjgisOverlapType.zjgisOverlapIntersect)
                {
                    ESRI.ArcGIS.AnalysisTools.Intersect intersect = new ESRI.ArcGIS.AnalysisTools.Intersect();
                    intersect.in_features = in_featureclass1 + ";" + in_featureclass2; ;
                    intersect.out_feature_class = OutputName;
                    intersect.join_attributes = JoinAttributes[this.cmbAtt.SelectedIndex];
                    intersect.output_type = "INPUT";
                    suc = GeoprocessorHelper.Execute(intersect, GP, out msg);
                }
                if ((chk_AutoLoad.Checked) && suc)
                {
                    OutputFC = GP.Open(OutputName) as IFeatureClass;
                    IFeatureLayer pFLayer = new FeatureLayer();
                    pFLayer.FeatureClass = OutputFC;
                    pFLayer.Name = OutputName.Substring(OutputName.LastIndexOf("\\") + 1);
                    FocusMap.AddLayer(pFLayer);
                }
                System.Windows.Forms.Cursor.Current = Cursors.Default;
                try
                {
                    if (in_featureclass1.EndsWith(".lyr"))
                        File.Delete(in_featureclass1);
                    if (in_featureclass2.EndsWith(".lyr"))
                        File.Delete(in_featureclass2);
                }
                catch
                {
                    //防止文件删除异常
                }
                if (suc)
                    MsgHelper.ShowInfomationMsgbox(this.cmbOverlayType.Text + "处理完毕！");
                else
                {
                    LogHelper.WriteErrLog("叠置分析失败： " + msg + ".选择的图层:" + in_featureclass1 + ";" + in_featureclass2);
                    MsgHelper.ShowErrorMsgbox(this.cmbOverlayType.Text + "失败： " + msg);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrLog("叠置分析出错! " + ex.Message + ".选择的图层:" + in_featureclass1 + ";" + in_featureclass2);
                MsgHelper.ShowErrorMsgbox(ex.Message);
            }
            finally
            {
                System.Windows.Forms.Cursor.Current = Cursors.Default;
                this.Progress.Visible = false;
                this.lblAll.Text = "";
                this.CmdOK.Enabled = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="featureClass"></param>
        /// <param name="aliasName1"></param>
        /// <param name="aliasName2"></param>
        private void GetDiffFeatureClass(IFeatureClass featureClass, string aliasName1, string aliasName2)
        {
            if (featureClass == null)
                return;
            IQueryFilter pQFilter = new QueryFilter();
            string FID1 = "FID_" + aliasName1;
            string FID2 = "FID_" + aliasName2;
            FID1 = GetLikeFieldName(featureClass.Fields, FID1);
            FID2 = GetLikeFieldName(featureClass.Fields, FID2);
            pQFilter.SubFields = FID1 + "," + FID2;
            pQFilter.WhereClause = FID1 + "> -1 and " + FID2 + "> -1";
            IFeatureCursor pFCursor = featureClass.Update(pQFilter, false);
            while (pFCursor.NextFeature() != null)
            {
                pFCursor.DeleteFeature();
            }
            Marshal.ReleaseComObject(pFCursor);
            pFCursor = null;

        }
        /// <summary>
        /// 获取分析的图层名称
        /// </summary>
        /// <param name="selected"></param>
        /// <param name="featurelayer"></param>
        /// <returns></returns>
        private string GetLayerName(bool selected, IFeatureLayer featurelayer)
        {
            string path = PathHelper.GetAppPath() + "\\temp";
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            string lyrname = featurelayer.Name;
            IFeatureClass fcl = featurelayer.FeatureClass;
            if (lyrname.Contains(".") && !lyrname.ToLower().EndsWith(".shp")) lyrname = lyrname.Substring(lyrname.IndexOf(".") + 1);
            string name = path + "\\" + lyrname + ".lyr";
            if (!selected)
            {
                if (cmbExtent.SelectedIndex == 0)   //当前视图范围
                {
                    SelectFeature(featurelayer);
                    //LayerHelper.SaveLayerFile(featurelayer, name);
                }
                else
                {
                    IFeatureSelection featsel = featurelayer as IFeatureSelection;
                    featsel.Clear();
                    //name = FeatureClassHelper.GetFullName(featurelayer.FeatureClass);
                }
            }
            LayerHelper.SaveLayerFile(featurelayer, name);
            if (!File.Exists(name)) return "";
            return name;
        }

        /// <summary>
        /// 获取输出路径
        /// </summary>
        /// <returns></returns>
        private string GetOutName()
        {
            string path = txtFile.Text;
            string name = cmbOverlayType.Text;
            bool isshp = false;
            IWorkspace wks = null;
            if ((txtFile.Text.ToLower().EndsWith(".gdb") || txtFile.Text.ToLower().Contains(".gdb\\")))
            {
                if (txtFile.Text.ToLower().Contains(".gdb\\"))
                    path = cmbOverlayType.Text.Trim().Substring(0, cmbOverlayType.Text.Trim().LastIndexOf("\\"));
                if (!Directory.Exists(path))
                    path = "C:\\";
                wks = PlanningGIS.ArcGIS.WorkspaceHelper.OpenGDBWorkspace(path);
            }
            else if ((txtFile.Text.ToLower().EndsWith(".mdb") || txtFile.Text.ToLower().Contains(".mdb\\")))
            {
                if (txtFile.Text.ToLower().Contains(".mdb\\"))
                    path = cmbOverlayType.Text.Trim().Substring(0, cmbOverlayType.Text.Trim().LastIndexOf("\\"));
                wks = PlanningGIS.ArcGIS.WorkspaceHelper.OpenAccessWorkspace(path);
            }
            else if ((txtFile.Text.ToLower().EndsWith(".sde") || txtFile.Text.ToLower().Contains(".sde\\")))
            {
                if (txtFile.Text.ToLower().Contains(".sde\\"))
                    path = cmbOverlayType.Text.Trim().Substring(0, cmbOverlayType.Text.Trim().LastIndexOf("\\"));
                wks = PlanningGIS.ArcGIS.WorkspaceHelper.OpenSDEWorkspaceFromFile(path);
            }
            else
            {
                if (!Directory.Exists(path))
                    path = "C:\\";
                wks = PlanningGIS.ArcGIS.WorkspaceHelper.OpenShpWorkspace(path);
                isshp = true;
            }
            if (wks == null)
                return "";
            int index = 0;
            string newName = name;
            while (((IWorkspace2)wks).get_NameExists(esriDatasetType.esriDTFeatureClass, newName))
            {
                index++;
                newName = name + "_" + index;
            }
            if (isshp)
                newName += ".shp";
            return txtFile.Text + "\\" + newName;
        }

        /// <summary>
        /// 获取最相似的属性名
        /// </summary>
        /// <param name="pFields"></param>
        /// <param name="FieldName"></param>
        /// <returns></returns>
        private string GetLikeFieldName(IFields pFields, string FieldName)
        {            
            int MaxSameLength = -1;
            string MaxSameFieldName = "";
            for (int i = 0; i < pFields.FieldCount; i++)
            {
                IField pField = pFields.get_Field(i);
                if (pField.Name == FieldName)
                {
                    return FieldName;
                }
                else if ((pField.Name.Length < FieldName.Length) && (pField.Name == FieldName.Substring(0, pField.Name.Length)))
                {
                    if (pField.Name.Length > MaxSameLength)
                    {
                        MaxSameLength = pField.Name.Length;
                        MaxSameFieldName = pField.Name;
                    }
                }
            }
            return MaxSameFieldName;
        }

        /// <summary>
        /// 根据当前视图范围选择要素
        /// </summary>
        /// <param name="pSelLayer"></param>
        /// <param name="bActiveViewExtent"></param>
        /// <returns></returns>
        private bool SelectFeature(IFeatureLayer pSelLayer)
        {
            ISpatialFilter pSpatialFilter = new SpatialFilter();
            pSpatialFilter.Geometry = (FocusMap as IActiveView).Extent;
            pSpatialFilter.GeometryField = pSelLayer.FeatureClass.ShapeFieldName;
            pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            ((IFeatureSelection)pSelLayer).SelectFeatures(pSpatialFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
            return true;
        }
        
	}
    
}
